package com.tanhua.oss;

import cn.hutool.core.util.ArrayUtil;
import com.aliyun.oss.OSSClient;
import com.tanhua.enums.FileTypeEnum;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @ClassName: OssTemplate
 * @Author:王晨晗
 * @Description: 文件上传模板类
 * @Date: 2021/12/27/18:59
 */
public class OssTemplate {
    private OssProperties ossProperties;

    private OSSClient ossClient;

    public OssTemplate(OssProperties ossProperties) {
        this.ossProperties = ossProperties;
        this.ossClient = new OSSClient(ossProperties.getEndpoint(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
    }

    /**
     * @param uploadFile: 传递文件的形式
     * @description 此方法用于文件上传, 不进行格式校验, 只需传递文件对象即可
     * @updateTime 2021/12/28 9:51
     * @return: java.lang.String
     */
    public String uploadFile(MultipartFile uploadFile) {
        //1.确定文件保存路径
        //1.1 获取源文件名
        String fileName = uploadFile.getOriginalFilename();
        //1.2 生成文件保存路径
        String filePath = getFilePath(fileName);
        //上传阿里云
        try {
            ossClient.putObject(ossProperties.getBucketName(), filePath, new ByteArrayInputStream(uploadFile.getBytes()));
        } catch (Exception e) {
            return null;    //异常捕获,表示上传失败,返回null
        }
        //上传成功,返回文件保存地址url
        return ossProperties.getUrlPrefix() + filePath;
    }

    /**
     * @param uploadFile   传递文件的形式
     * @param fileTypeEnum 校验的格式枚举类型
     * @description 文件上传方法 重载形式 加入了格式校验
     * @updateTime 2021/12/28 10:02
     * @return: java.lang.String
     */
    public String uploadFile(MultipartFile uploadFile, FileTypeEnum fileTypeEnum) {
        //调用格式校验方法
        boolean flag = fileFormat(uploadFile.getOriginalFilename(), fileTypeEnum);
        //判断校验是否通过
        if (!flag) {
            throw new FileFormatExecption("文件格式有误");    //未通过,抛出文件格式异常
        }
        //校验通过,进行文件上传
        String filePath = uploadFile(uploadFile);
        //返回文件保存地址url
        return filePath;
    }

    /**
     * @param fileName 源文件名
     * @description 文件路径生成
     * @updateTime 2021/12/28 9:51
     * @return: java.lang.String
     */
    public String getFilePath(String fileName) {
        DateTime dateTime = new DateTime();     //获取当前日期
        return "images/" + dateTime.toString("yyyy") + "/" +
                dateTime.toString("MM") + "/" +
                dateTime.toString("dd") + "/" + System.currentTimeMillis() +
                RandomUtils.nextInt(100, 9999) + "." +
                StringUtils.substringAfterLast(fileName, ".");
    }

    /**
     * @param fileName     源文件名
     * @param fileTypeEnum 校验格式的枚举类
     * @description 文件格式校验方法(如果用户需要可进行调用)
     * @updateTime 2021/12/28 10:06
     * @return: boolean
     */
    /*public boolean fileFormat(String fileName, FileTypeEnum fileTypeEnum) {
        //获取文件后缀名
        String rx = fileName.substring(fileName.lastIndexOf("."));
        //将枚举的数组属性封装到集合中 , 再判断集合是否包含该文件的格式类型
        boolean result = Arrays.asList(fileTypeEnum.getFileType()).contains(rx);
        //返回比较结果
        return result;
    }*/

    /**
     * @param fileName
     * @param fileTypeEnums
     * @description 多文件格式校验
     * @updateTime 2021/12/31 16:09
     * @return: boolean
     */
    public boolean fileFormat(String fileName, FileTypeEnum... fileTypeEnums) {
        //获取文件后缀名
        String rx = fileName.substring(fileName.lastIndexOf("."));
        String[] fileType = getFileTypes(fileTypeEnums);      //获取文件类型集合
        //将枚举的数组属性封装到集合中 , 再判断集合是否包含该文件的格式类型
        boolean result = Arrays.asList(fileType).contains(rx);
        //返回判断结果
        return result;
    }

    /**
     * @param uploadFiles
     * @description 批量上传文件
     * @updateTime 2021/12/31 16:01
     * @return: java.util.List<java.lang.String>
     */
    public List<String> uploadFile(MultipartFile[] uploadFiles) {
        List<String> picUrls = new ArrayList<>();
        for (MultipartFile uploadFile : uploadFiles) {
            //1.确定文件保存路径
            //1.1 获取源文件名
            String fileName = uploadFile.getOriginalFilename();
            //1.2 生成文件保存路径
            String filePath = getFilePath(fileName);
            //上传阿里云
            try {
                ossClient.putObject(ossProperties.getBucketName(), filePath, new ByteArrayInputStream(uploadFile.getBytes()));
            } catch (Exception e) {
                return null;    //异常捕获,表示上传失败,返回null
            }
            //上传成功,返回文件保存地址url
            picUrls.add(filePath);
        }
        return picUrls;
    }

    /**
     * @param uploadFiles
     * @param fileTypeEnums
     * @description 上传多文件 , 指定文件格式(可进行多种格式校验),格式不正确,则上传失败.
     * @updateTime 2021/12/31 16:03
     * @return: java.util.List<java.lang.String>
     */
    public List<String> uploadFile(MultipartFile[] uploadFiles, FileTypeEnum... fileTypeEnums) {
        //判断文件的格式是否符合要求
        for (MultipartFile uploadFile : uploadFiles) {
            //对文件进行每一种格式的校验.通过
            boolean result = fileFormat(uploadFile.getOriginalFilename(), fileTypeEnums);
            if (!result) {
                return null;
            }
        }
        List<String> picUrls = new ArrayList<>();
        for (MultipartFile uploadFile : uploadFiles) {
            String filePath = uploadFile(uploadFile);
            picUrls.add(filePath);
        }
        return picUrls;
    }

    /**
     * @description 获取文件类型枚举的数据,封装到数组返回
     * @param fileTypeEnums
     * @updateTime 2021/12/31 23:17
     * @return: java.lang.String[]
     */
    public String[] getFileTypes(FileTypeEnum...fileTypeEnums){
        String[] fileType = new String[]{};  //用于保存所有的文件类型集合
        for (FileTypeEnum fileTypeEnum : fileTypeEnums) {
            //将数组合并赋值给filetype
            fileType = ArrayUtil.addAll(fileType , fileTypeEnum.getFileType());
        }
        return fileType;
    }
}
